<?php
namespace App\Common\Lib\Err;

use App\Common as com;
use App\Common\Lib\Err\BaseException as nameBaseException;

class BaseException extends com\Lib\LibBase {

	/**
	 * 异常类
	 * @var string
	 */
	protected static ?string $exceptionClass = null;

	public static int $isShowErrInfo = 1; // 是否输出错误文本信息（最终决定是否输出的配置在"app_debug"）

	/** 1：异常级别-严重 */
	protected static int $exceptionLevel_Severity = 1;
	/** 2：异常级别-警告 */
	protected static int $exceptionLevel_Warning = 2;
	/** 3：异常级别-普通 */
	protected static int $exceptionLevel_Notice = 3;

	/**
	 * 输出错误信息
	 * @param int $code
	 * @param string $statusStr
	 * @return void
	 */
	protected static function show( int $code, string $statusStr = null ){
		if( self::$isShowErrInfo != 1 ) return;
		if( ! config('web.debugInfo.isDebug') ) return;
		$debug_backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 4 );
		echo "错误码：{$code}<br />";
		echo "错误码转换：" . com\Cla\Err\Code::getUserText( $code ) . "<br />";
		echo "错误说明：{$statusStr}<br />";
		echo "抛出位置：{$debug_backtrace[3]['file']} : {$debug_backtrace[3]['line']}";
		echo "<hr />";
	}

	/**
	 * 抛出异常，级别：严重
	 * @param string $msg 错误说明。[null][默认]没有
	 * @param int $code 错误码
	 * @param array $data 其他数据
	 * @return nameBaseException\Throw_
	 */
	public static function severity( string $msg, int $code = 0, array $data = [] ):nameBaseException\Throw_ {
		$param['data'] = $data;
		$param['data']['level'] = self::$exceptionLevel_Severity;
		return self::throwManage( $msg, $code, $param );
	}

	/**
	 * 抛出异常，级别：警告
	 * @param string $msg 错误说明。[null][默认]没有
	 * @param int $code 错误码
	 * @param array $data 其他数据
	 * @return nameBaseException\Throw_
	 */
	public static function warning( string $msg, int $code = 0, array $data = [] ):nameBaseException\Throw_ {
		$param['data'] = $data;
		$param['data']['level'] = self::$exceptionLevel_Warning;
		return self::throwManage( $msg, $code, $param );
	}

	/**
	 * 抛出异常，级别：提醒
	 * @param string $msg 错误说明。[null][默认]没有
	 * @param int $code 错误码
	 * @param array $data 其他数据
	 * @return nameBaseException\Throw_
	 */
	public static function notic( string $msg, int $code = 0, array $data = [] ):nameBaseException\Throw_ {
		$param['data'] = $data;
		$param['data']['level'] = self::$exceptionLevel_Notice;
		return self::throwManage( $msg, $code, $param );
	}

	/**
	 * 抛出异常
	 * @param string $msg 错误说明。[null][默认]没有
	 * @param int $code 错误码
	 * @param array $param 参数数组 <br />
	 * ················· [可空](mixed)	$param['data']	说明：异常级别(参考：self::$exceptionLevel_xxx)。	<br />
	 * ················· [可空/多选_A/必须](unknown_type)	$param['AAAAA']	说明：AAAAA	<br />
	 * @return nameBaseException\Throw_
	 */
	private static function throwManage( string $msg, int $code = 0, array $param = [] ):nameBaseException\Throw_ {
		return self::getThrow( $msg, $code, $param );
	}

	/**
	 * 抛出异常
	 * @param string $msg 错误说明。[null][默认]没有
	 * @param int $code 错误码
	 * @param array $param 参数数组 <br />
	 * ················· [可空](array)	$param['data']	说明：其他数据	<br />
	 * ················· [可空/多选_A/必须](unknown_type)	$param['AAAAA']	说明：AAAAA	<br />
	 * @return nameBaseException\Throw_
	 */
	public static function getThrow( string $msg, int $code = 0, array $param = [] ):nameBaseException\Throw_ {
		// ...
		$param['data'] = $param['data'] ?? [];
		//
		$codeStr = com\Lib\Err\Code::getUserText( $code );
		if( '' != $codeStr ) {
			if( strpos( $msg, '{msg}' ) !== false ){
				$msg = str_replace( '{msg}', $codeStr, $msg );
			}else{
				if( empty( $msg ) ){
					$msg = $msg . ' ';
					$msg .= '[' . $codeStr . ']';
				}
			}
		}
		//
		$exception = new static::$exceptionClass( $msg, $code );
		//
		$param['data']['errInfo'] = self::buildErrData( $msg, $code, $param );
		//
		if( ! empty( $param['data'] ) ) $exception->setData( $param['data'] );
		//
		// self::show( $code, $paramMain['errData']['statusStr'] ?? null );
		//
		return $exception;
	}

	/**
	 * 生成错误信息
	 * @param string $msg 错误说明。[null][默认]没有
	 * @param int $code 错误码
	 * @param array $param
	 * @return array 错误信息
	 */
	protected static function buildErrData( string $msg, int $code = 0, array $param = [] ){
		$debug_backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 4 );
		return [
			'code' => $code,
			'codeStr' => com\Cla\Err\Code::getUserText( $code ),
			'msg' => $msg,
			'param' => $param['data'],
			'file' => $debug_backtrace[3]['file'],
			'line' => $debug_backtrace[3]['line'],
		];
	}

	/**
	 * @param \Throwable $e
	 * @return string
	 */
	public static function getSimpleShowExceptionInfo( \Throwable $e ):string {
		$echoStr = "\n【simpleShowExceptionInfo】\n\n";
		$echoStr .= '[' . $e->getCode() . '] ' . $e->getMessage();
		$echoStr .= "\n\n";
		$echoStr .= "The error: " . $e->getFile() . "(" . $e->getLine() . ")";
		$echoStr .= "\n\n";
		$echoStr .= "Stack trace:\n";
		$i = 0;
		foreach ( $e->getTrace() as $traceValue ){
			$i++;
			//
			if( isset( $traceValue['file'] ) ){
				$echoStr .= "#{$i} {$traceValue['file']}({$traceValue['line']})\n";
			}else{
				$echoStr .= "#{$i} 未知数据\n";
			}
		}
		//
		return $echoStr;
	}

}
